package archer.framework.common.entity;

import archer.framework.common.repository.condition.QueryCondition;
import archer.framework.common.repository.dao.GenericDao;
import archer.framework.utils.ContextUtils;
import com.avaje.ebean.Query;
import jodd.json.meta.JSON;

import javax.persistence.MappedSuperclass;
import java.util.List;
import java.util.Map;

/**
 * @author christ
 * @date 2016/6/1
 */
@MappedSuperclass
public abstract class ActiveRecordEntity {

    public static class Find<T> {

        private Class<T> type;

        public Find(Class<T> type) {

            this.type = type;
        }

        public Query<T> byCondition(QueryCondition condition) {

            return ActiveRecordEntity.dao().find(type, condition);
        }

        public T byId(Object id) {

            return ActiveRecordEntity.dao().findById(type, id);
        }

        public Query<T> query() {

            return ActiveRecordEntity.dao().find(type);
        }

        public List<T> all() {

            return query().findList();
        }

        public Query<T> first() {

            return ActiveRecordEntity.dao().findFirst(type);
        }

        public Query<T> top(Integer rows) {

            return ActiveRecordEntity.dao().findTop(type, rows);
        }

        public Query<T> exists(String alias, Query subQuery) {
            return ActiveRecordEntity.dao().findExists(type, alias, subQuery);
        }

        public Query<T> notExists(String alias, Query subQuery) {
            return ActiveRecordEntity.dao().findNotExists(type, alias, subQuery);
        }

        public Query<T> existsSubQuery(String subAlias, String rawSql) {
            return ActiveRecordEntity.dao().findExistsSubQuery(type, subAlias, rawSql);
        }
    }

    @JSON(include = false)
    public void store() {

        dao().store(this);
    }

    @JSON(include = false)
    public <T> T storeAndQuery() {

        return (T) dao().storeAndQuery(this);
    }

    @JSON(include = false)
    public boolean duplicated(String field) {

        return dao().duplicated(this, field);
    }

    @JSON(include = false)
    public boolean duplicated(String idField, String field) {

        return dao().duplicated(this, idField, field);
    }

    @JSON(include = false)
    public boolean duplicated(String field, Map rangeMap) {

        return dao().duplicated(this, field, rangeMap);
    }

    @JSON(include = false)
    public boolean duplicated(String idField, String field, Map rangeMap) {

        return dao().duplicated(this, idField, field, rangeMap);
    }

    @JSON(include = false)
    public void delete() {

        dao().delete(this);
    }

    @JSON(include = false)
    public void logicalDelete() {

        dao().logicalDelete(this);
    }

    @JSON(include = false)
    public static GenericDao dao() {

        return ContextUtils.getBean("genericDao", GenericDao.class);
    }

}
